package com.licheedev.myutils;

import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.JsonSyntaxException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

public class GsonUtil {

    private static final String TAG = "GsonUtil";

    private static Gson gson = buildGson();

    private static boolean enableLog = true;

    public static boolean isEnableLog() {
        return enableLog;
    }

    public static void setEnableLog(boolean enableLog) {
        GsonUtil.enableLog = enableLog;
    }

    private static void log(Throwable tr) {
        if (enableLog) {
            Log.w(TAG, tr);
        }
    }

    @NonNull
    public static String toJson(Object srcObj) {
        return gson.toJson(srcObj);
    }

    @Nullable
    public static <T> T toObject(String src, Class<T> classOfT) {
        T result = null;
        try {
            result = gson.fromJson(src, classOfT);
        } catch (Exception e) {
            log(e);
        }
        return result;
    }

    @Nullable
    public static <T> T toObject(JsonElement src, Type superClass) {
        T result = null;
        try {
            result = gson.fromJson(src, superClass);
        } catch (Exception e) {
            log(e);
        }
        return result;
    }

    @Nullable
    public static <T> T toObject(String json, Type typeOfT) {
        T result = null;
        try {
            result = gson.fromJson(json, typeOfT);
        } catch (Exception e) {
            log(e);
        }
        return result;
    }

    @NonNull
    public static <T> List<T> toList(JsonElement jsonData, Class<T> cls) {
        ArrayList<T> list = new ArrayList<>();
        try {
            // 将JsonElement转换成JsonArray
            JsonArray jsonArray = jsonData.getAsJsonArray();
            // Iterator处理
            for (JsonElement jsonElement : jsonArray) {
                // 提取JsonElement
                // JsonElement转换成String
                String json = jsonElement.toString();
                // String转化成JavaBean
                T bean = gson.fromJson(json, cls);
                list.add(bean);
            }
        } catch (Exception e) {
            log(e);
        }
        return list;
    }

    @NonNull
    public static <T> List<T> toList(String json, Class<T> clazz) {
        List<T> lst = new ArrayList<>();
        try {
            JsonArray array = JsonParser.parseString(json).getAsJsonArray();
            for (final JsonElement elem : array) {
                lst.add(gson.fromJson(elem, clazz));
            }
        } catch (Exception e) {
            log(e);
        }
        return lst;
    }

    @NonNull
    public static <T> List<T> toList(String json, Type typeOfT) {
        try {
            return gson.fromJson(json, typeOfT);
        } catch (Exception e) {
            log(e);
            return new ArrayList<>();
        }
    }

    public static Gson buildGson() {
        if (gson == null) {
            gson = new GsonBuilder()
                .disableHtmlEscaping()
                .serializeNulls()
                .registerTypeAdapter(String.class, new StringAdapter())
                .registerTypeAdapter(Integer.class, new IntegerDefault0Adapter())
                .registerTypeAdapter(Double.class, new DoubleDefault0Adapter())
                .registerTypeAdapter(Long.class, new LongDefault0Adapter())
                .create();
        }
        return gson;
    }

    private static class StringAdapter implements JsonSerializer<String>, JsonDeserializer<String> {
        @Override
        public String deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
            if (json instanceof JsonPrimitive) {
                return json.getAsString();
            } else {
                return json.toString();
            }
        }

        @Override
        public JsonElement serialize(String src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }

    private static class IntegerDefault0Adapter implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
        @Override
        public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
            try {
                if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定义为int类型,如果后台返回""或者null,则返回0
                    return 0;
                }
            } catch (Exception ignore) {
            }
            try {
                return json.getAsInt();
            } catch (NumberFormatException e) {
                throw new JsonSyntaxException(e);
            }
        }

        @Override
        public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }

    private static class DoubleDefault0Adapter implements JsonSerializer<Double>, JsonDeserializer<Double> {
        @Override
        public Double deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            try {
                if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定义为double类型,如果后台返回""或者null,则返回0.00
                    return 0.00;
                }
            } catch (Exception ignore) {
            }
            try {
                return json.getAsDouble();
            } catch (NumberFormatException e) {
                throw new JsonSyntaxException(e);
            }
        }

        @Override
        public JsonElement serialize(Double src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }

    private static class LongDefault0Adapter implements JsonSerializer<Long>,
        JsonDeserializer<Long> {
        @Override
        public Long deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
            try {
                if (json.getAsString().equals("") || json.getAsString().equals("null")) {//定义为long类型,如果后台返回""或者null,则返回0
                    return 0L;
                }
            } catch (Exception ignore) {
            }
            try {
                return json.getAsLong();
            } catch (NumberFormatException e) {
                throw new JsonSyntaxException(e);
            }
        }

        @Override
        public JsonElement serialize(Long src, Type typeOfSrc, JsonSerializationContext context) {
            return new JsonPrimitive(src);
        }
    }
    
}
